package com.cynoware.busappmas.util;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.SystemClock;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;

public class sys{
    static final String TAG = "DrinkMonitor";
    
    public static final String SU = get_su();
    public static final int SU_STYLE = get_su_style();
    
    static public boolean sleep(long time){
        try{
            Thread.sleep(time);
        }catch(InterruptedException e){
            return false;
        }
        return true;
    }
    
    static String smbFix(String path){
        path = path.replaceAll("\\\\", "/");
        if(!path.startsWith("smb:")){
            if(!path.startsWith("//")){
                if(path.startsWith("/"))
                    path = "/" + path;
                else
                    path = "//" + path;
            }
            path = "smb:" + path;
        }
        return path;
    }
    static boolean fileExists(String path){
        return new File(path).exists();
    }
    
    static public String formatDate(Date date, String style){
        return new SimpleDateFormat(style, Locale.US).format(date);
    }
    
    static public Date dateAddSeconds(Date date, int sec){
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
        calendar.add(Calendar.SECOND, sec);
        
        return calendar.getTime();
    }
    
    static Date parseDate(String string, String style) throws ParseException{
       return new SimpleDateFormat(style, Locale.US).parse(string);
    }
    
    static int parseInt(String string, int radix, int defaultValue){
        if(string == null) return defaultValue;
        else{
            try{
                return Integer.parseInt(string, radix);
            }
            catch(NumberFormatException ex){
                return defaultValue;
            }
        }
    }
    
    static public boolean writeFile(String path, String str){
        boolean ret = true;
        File file = new File(path);
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        PrintStream outputStream = null;
        try{
            outputStream = new PrintStream(new FileOutputStream(file));
            outputStream.print(str);
        }catch (FileNotFoundException e){
            e.printStackTrace();
            ret = false;
        }finally{
            if(outputStream != null){
                outputStream.close();
            }
        }
        return ret;
    }
    
    static public String readFile(String path){
        File file = new File(path);
        BufferedReader reader = null;
        String laststr = "";
        try{
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            while ((tempString=reader.readLine())!=null){
                laststr = laststr + tempString;
            }
            reader.close();
        }catch (IOException e){
            //e.printStackTrace();
        }finally{
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return laststr;
    }
    
    static public String ReadFileInternal(Context context, String path){
        BufferedReader reader = null;
        String laststr = "";
        try{
            String s = null;
            InputStreamReader inputStream = new InputStreamReader(context.openFileInput(path));
            reader = new BufferedReader(inputStream);
            while((s = reader.readLine()) != null){
                laststr = laststr + s;
            }
        }catch (IOException e){
        }finally{
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return laststr;
    }
    
    static void WriteFileInternal(Context context, String path, String str){        
        PrintStream outputStream = null;
        try{
            outputStream = new PrintStream(context.openFileOutput(path, Context.MODE_PRIVATE));
            outputStream.print(str);
            outputStream.flush();            
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }finally{
            if(outputStream != null){
                outputStream.close();
            }
        }
    }    
    
    static int copyStream(InputStream in, OutputStream out) throws IOException{
        int size = 0;
        byte[] buffer = new byte[4096];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
            size += read;
        }
        return size;
    }
    
    @SuppressLint("NewApi")
    static boolean isValidProduct(){
        String cmdline = readFile("/proc/cmdline");
        if(cmdline.contains("hw_name=")) return true;
        
        @SuppressWarnings("deprecation")
		String version = Build.RADIO;
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            version = Build.getRadioVersion();
        }
        if(version.contains("CPU:")
            && version.contains("i.MX6")
            && (version.contains("Board: general")
                || version.contains("Board: S10")
                || version.contains("Board: C6")))
            return true;
        
        return false;
    }
        
    static void uiRun(Activity activity, Runnable runnable){
        new BlockingOnUIRunnable(activity, runnable).run();
    }
    
    static void thread(final Object lock, final Runnable runnable){
        new Thread(){ public void run(){
            try{
                synchronized(lock){
                    runnable.run();
                }
            }catch(Exception e){
                e.printStackTrace();
        }}}.start();
    }
    
    static class BlockingOnUIRunnable
    {
        Activity activity_;
        Runnable runnable_;
        Runnable myRunnable_;
        BlockingOnUIRunnable(Activity activity, Runnable runnable){
            activity_ = activity;
            runnable_ = runnable;
            
            myRunnable_ = new Runnable(){
                public void run(){
                    synchronized(activity_){
                        runnable_.run();
                    }
                    synchronized(this){
                        this.notify();
                    }
                }
            };
        }
        
        void run(){
            synchronized(myRunnable_){
                long start = SystemClock.elapsedRealtime();
                activity_.runOnUiThread(myRunnable_);
                try{
                    myRunnable_.wait();
                    long end = SystemClock.elapsedRealtime();
                    if(end - start >= 30)
                        Log.i(TAG, String.format("time = %d", end - start));
                    else if(end - start >= 20)
                        Log.i(TAG, String.format("time = %d", end - start));
                    else if(end - start >= 10)
                        Log.i(TAG, String.format("time = %d", end - start));                    
                }catch(InterruptedException e){}
            }
        }
    }
    
    static void setBrightness(Window win, boolean show) {
        WindowManager.LayoutParams lp = win.getAttributes();
        if(show){
            lp.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL;
            //SysUtil.setScreenBlank(false);
        }
        else{
            lp.screenBrightness = 0.01f;
            //SysUtil.setScreenBlank(true);
        }
        win.setAttributes(lp);
    }
    
    static void setLongOpenDialog(Window win){
        win.setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        win.setFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        //win.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        sys.setBrightness(win, true);
    }
    
    static void setLongOpenWindow(Window win){
        win.setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        win.setFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD,WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        win.setFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        win.setFlags(WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON,WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
        win.setFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        win.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        sys.setBrightness(win, true);
    }
    
    public static void setLongOpenActivity(Activity activity){
        activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
        activity.setRequestedOrientation( android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        //activity.setRequestedOrientation( android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        setLongOpenWindow(activity.getWindow());
    }
    
    public static String get_su(){
        File app = new File("/system/xbin/ts");
        if(app.exists() && app.canExecute())
            return "ts";    //Cynoware special su application
        else
            return "su";
    }
    
    private static class Worker extends Thread {
        private final Process process;
        private Integer exit;
        private Worker(Process process) {
          this.process = process;
        }
        public void run() {
          try { 
            exit = process.waitFor();
          } catch (InterruptedException ignore) {
            return;
          }
        }  
      }
    
    public static int get_su_style(){
        try{
            Process process = Runtime.getRuntime().exec(
                    new String[]{SU, "-c", "ls /"});
            int code = -1;//process.waitFor();
            
            Worker worker = new Worker(process);
            worker.start();
            try {
                worker.join(3000);
                if (worker.exit != null)
                    code = worker.exit;
                else
                    throw new IOException();
            } catch(InterruptedException ex) {
                worker.interrupt();
            } finally {
                process.destroy();
            }
            
            if(code == 0){
                //call format -- .exec(new String[]{"su", "-c", command_line})
                return 0;
            }
            else{
                //call format -- .exec("su -c " + command_line)
                return 1;
            }
        }
        catch(Exception e){ 
        }
        return -1;
    }

    public static Process su_exec(String cmd) throws IOException{
        Log.d(TAG, "run cmd: " + cmd);
        if(SU_STYLE == 0){
            return Runtime.getRuntime().exec(new String[]{SU, "-c", cmd});
            //String sucmd = String.format("\"%s /data/busybox sh -c '%s'\"", SU, cmd);
            //Process p = Runtime.getRuntime().exec(new String[]{"/data/busybox", "sh", "-c", sucmd});
            //Process p = Runtime.getRuntime().exec("/data/busybox sh -c " + sucmd);
            //return p;
        }
        else if(SU_STYLE == 1){
            //return Runtime.getRuntime().exec(String.format("%s -c %s", SU, cmd));            
            return Runtime.getRuntime().exec(new String[]{SU, "-c", "sh", "-c", cmd});
        }
        else
            throw new IOException("Can not call " + SU);
    }
    
    
    
    
    public static boolean hasUpdateUSB(String usbFile, String dateFile){
        File src = new File(usbFile);
        if(!src.exists()) return false;
        long lastModified = src.lastModified();
        
        String sdcard = Environment.getExternalStorageDirectory().getPath();
        String datePath = sdcard + dateFile;
        if(new File(datePath).exists()){
            String str = sys.readFile(datePath);
            long lastUpdate = Long.parseLong(str);
            if(lastModified == lastUpdate) return false;
        }
        
        return true;
    }
    
    public static boolean hasUpdateUSBAPK(){
        return hasUpdateUSB("/udisk/drinkmonitor.apk", "/drinkmonitor/updateapk.txt");
    }
    
    public static boolean hasUpdateUSBIni(){
        return hasUpdateUSB("/udisk/terminal.ini", "/drinkmonitor/updateini.txt");
    }
    
    public static void updateUSB(
            Activity activity,
            String usbFile,
            String dateFile,
            String desFile
            ){
        File src = new File(usbFile);
        if(!src.exists()) return;
        long lastModified = src.lastModified();
        
        String sdcard = Environment.getExternalStorageDirectory().getPath();
        String desPath = sdcard + desFile;
        File des = new File(desPath);
        File dir = new File(des.getParent());
        if(!dir.exists()) dir.mkdirs();

        //Copy file
        boolean success = true;
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(src);
            out = new FileOutputStream(des);
            copyStream(in, out);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
        } catch (Exception e) {
            success = false;
        }
        
        if(success){
            String datePath = sdcard + dateFile;
            sys.writeFile(datePath, String.format("%d", lastModified));
        }
    }
     
    
    public static String getRootURL(String fullpath){
        String path0 = fullpath.replaceAll("^.*//", "");
        String host = path0.replaceAll("/.*$", "");
        String prefix = fullpath.substring(0, fullpath.length() - path0.length());
        return prefix + host;
    }
    public static String getPathURL(String fullpath){
        String path0 = fullpath.replaceAll("^.*//", "");
        if(path0.equals(fullpath))
            return fullpath;
        return "/" + path0.replaceAll("^[^/]*/", "");
    }
    
    public static String getRelativeURL(String fullpath, String path){
        path = getPathURL(path);
        if(path.startsWith("/"))
            return getRootURL(fullpath) + path;
        else
            return fullpath.replaceAll("[^/]*$", "") + path;
    }    
}
